Adding Pagination To Vapor Query

When you have a request that returns many records, it’s almost required to paginate the response.


I found this QueryContainer extension that does just that:


QueryContainer extension


import Foundation
import Vapor
import Fluent

public struct BasicQuery: Codable {
    public let plain: Bool?
    public let page: Int?
    public let limit: Int?
    public let search: String?
}

extension QueryContainer {
    public var basic: BasicQuery? {
        let decoded = try? decode(BasicQuery.self)
        return decoded
    }
    
    public var plain: Bool? {
        return basic?.plain
    }
    
    public var page: Int? {
        return basic?.page
    }
    
    public var limit: Int? {
        return basic?.limit ?? 20
    }
    
    public var search: String? {
        return basic?.search
    }
    
}

//GET http://localhost:8080/api/countries?limit=20&page=1
extension QueryBuilder {
    public func paginate(on req: Request) throws -> Self {
        if let limit = req.query.basic?.limit {
            let page = req.query.basic?.page ?? 0
            let lower = (page * limit)
            return range(lower: lower, upper: (lower + limit))
        }
        return self
    }
}

Implementation

//GET /api/countries
aRoute.get(use: getAllPaginatedHandler)
...
func getAllPaginatedHandler(_ req: Request) throws -> Future<[CountrySQLite]> {
    return try CountrySQLite.query(on: req).paginate(on: req).all()
  }

Usage

To fetch 10th page, given that a page size is 20 records:

GET http://localhost:8080/api/countries?limit=20&page=10

You may checkout the full example on GitHub:

TestVaporCountries


Prev: Parent-Child relationships in Generic Fluent Models

Next: Revert Last Migration


Vapor 3 Tutorial Start


#pub #query #fluent #swift #pagination